package com.shyroke.daydayzhuansvc.service.impl;

import cn.hutool.core.util.StrUtil;
import com.querydsl.core.QueryResults;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.shyroke.daydayzhuanapi.constant.RedisKeyPrefix;
import com.shyroke.daydayzhuanapi.dto.CommentDto;
import com.shyroke.daydayzhuanapi.dto.UserMain;
import com.shyroke.daydayzhuanapi.entity.CommentEntity;
import com.shyroke.daydayzhuanapi.entity.QCommentEntity;
import com.shyroke.daydayzhuanapi.entity.QProjectEntity;
import com.shyroke.daydayzhuanapi.entity.RoleEntity;
import com.shyroke.daydayzhuanapi.mapper.CommentMapper;
import com.shyroke.daydayzhuandao.respository.CommentRepository;
import com.shyroke.daydayzhuandao.respository.UserRepository;
import com.shyroke.daydayzhuansvc.service.ICommentService;
import com.shyroke.daydayzhuansvc.util.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author youhj
 * @date 2019/9/26 0026 下午 1:23
 */
@Service
public class CommentService implements ICommentService {
    @Autowired
    private CommentRepository commentRepository;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private UserRepository userRepository;
    @Autowired
    private CommentMapper commentMapper;
    @Autowired
    private JPAQueryFactory factory;

    @Override
    public List<CommentDto> getCommentTreeList(Integer projectId,Integer start,Integer size) {

        List<CommentDto> rootList = new ArrayList<>();

        //所有数据
        List<CommentEntity> list = commentRepository.findByStatusAndArticleIdOrderByIdDesc(1,projectId);
        List<CommentDto> allList = list.stream().map(e->commentMapper.entityToDto(e)).collect(Collectors.toList());
        if(CollectionUtils.isEmpty(allList)){
            return null;
        }

        //获取所有根节点
        allList.forEach(e->{
            if(e.getReplyForId()==0){
                rootList.add(e);
            }
        });

        //为根节点设置子菜单，使用递归
        for(CommentDto root:rootList){
            //获取根节点下的所有子节点 使用getChild方法
            List<CommentDto> childList = getChild(root.getId(),allList);
            for(CommentDto project:childList){
                if(project.getCreateTime() != null){
                    project.setShowCreateTime(CommonUtil.getDateByFormat(project.getCreateTime(),"yyyy-MM-dd HH:mm:ss"));
                }
            }
            root.setChildren(childList);
        }

        for(CommentDto project:rootList){
            if(project.getCreateTime() != null){
                project.setShowCreateTime(CommonUtil.getDateByFormat(project.getCreateTime(),"yyyy-MM-dd HH:mm:ss"));
            }
        }

        return rootList;
    }

    @Override
    public TabelData<CommentDto> getComment(Page page, Integer projectId) {
        TabelData tabelData = new TabelData();

        Integer start = (page.getPage()-1)*page.getLimit();

        List<CommentDto> projects = this.getCommentTreeList(projectId,start,page.getLimit());

        int count = this.getIndexDataCount(projectId);

        tabelData.setCount(count);
        tabelData.setData(projects);


        return tabelData;
    }

    @Override
    public List<CommentDto> getComment(Integer projectId) {
        return this.getCommentTree(projectId);
    }

    private List<CommentDto> getCommentTree(Integer projectId) {
        List<CommentDto> rootList = new ArrayList<>();

        //所有数据
        List<CommentEntity> list = commentRepository.findByStatusAndArticleIdOrderByIdDesc(1,projectId);
        List<CommentDto> allList = list.stream().map(e->commentMapper.entityToDto(e)).collect(Collectors.toList());
        if(CollectionUtils.isEmpty(allList)){
            return null;
        }

        //获取所有根节点
        allList.forEach(e->{
            if(e.getReplyForId()==0){
                rootList.add(e);
            }
        });

        //为根节点设置子菜单，使用递归
        for(CommentDto root:rootList){
            //获取根节点下的所有子节点 使用getChild方法
            List<CommentDto> childList = getChild(root.getId(),allList);
            for(CommentDto project:childList){
                if(project.getCreateTime() != null){
                    project.setShowCreateTime(CommonUtil.getDateByFormat(project.getCreateTime(),"yyyy-MM-dd HH:mm:ss"));
                }
            }
            root.setChildren(childList);
        }

        for(CommentDto project:rootList){
            if(project.getCreateTime() != null){
                project.setShowCreateTime(CommonUtil.getDateByFormat(project.getCreateTime(),"yyyy-MM-dd HH:mm:ss"));
            }
        }

        return rootList;
    }

    @Override
    public int getIndexDataCount(Integer projectId) {
        List<CommentEntity> allList = commentRepository.findByStatusAndArticleIdOrderByIdDesc(1,projectId);
        return allList==null?0:allList.size();
    }

    @Override
    public void insert(CommentDto comment) {
        CommentEntity commentEntity = commentMapper.dtoToEntity(comment);
        commentRepository.save(commentEntity);
    }

    @Override
    public List<CommentEntity> getCommentByProjectId(Integer articleId) {
        return commentRepository.findByStatusAndArticleId(1,articleId);
    }

    @Override
    public TabelData<CommentDto> getTableDate(Page page, String title, UserMain user) {
        Set<RoleEntity> roleList = userRepository.findByName(user.getName()).getRoleList();
        Boolean isAdmin = UserUtils.isAdmin2(roleList);

        QCommentEntity qCommentEntity = QCommentEntity.commentEntity;
        QProjectEntity qProjectEntity = QProjectEntity.projectEntity;
        JPAQuery<CommentEntity> query = factory.selectFrom(qCommentEntity)
                .leftJoin(qProjectEntity).on(qCommentEntity.articleId.eq(qProjectEntity.id));

        if(!isAdmin){
            query = query.where(qProjectEntity.createId.eq(user.getId()));
        }
        if(StrUtil.isNotBlank(title)){
            query = query.where(qProjectEntity.title.like("%"+title+"%"));
        }

        QueryResults<CommentEntity> queryResults = query
                .offset(PageRequest.of(page.getPage() - 1, page.getLimit()).getOffset()).limit(page.getLimit())
                .orderBy(qCommentEntity.id.desc())
                .fetchResults();

        List<CommentDto> list = queryResults.getResults().stream().map(e -> commentMapper.entityToDto(e)).collect(Collectors.toList());

        return new TabelData(list,(int)queryResults.getTotal());
    }


    @Override
    public CommentEntity getCommentById(Integer id) {
        return commentRepository.findById(id).get();
    }

    @Override
    public void del(Integer id) {
        commentRepository.deleteById(id);
    }

    @Override
    public List<CommentDto> getNewComment() {
        List<CommentDto> commentList = RedisUtils.readList(RedisKeyPrefix.COMMENTLIST);
        if(CollectionUtils.isEmpty(commentList)){
            QCommentEntity qCommentEntity = QCommentEntity.commentEntity;
            QProjectEntity qProjectEntity = QProjectEntity.projectEntity;
            JPAQuery<CommentEntity> query = factory.selectFrom(qCommentEntity)
                    .leftJoin(qProjectEntity).on(qCommentEntity.articleId.eq(qProjectEntity.id));

            query = query.where(qCommentEntity.status.eq(1));

            List<CommentEntity> res = query.orderBy(qCommentEntity.createTime.desc()).limit(10).fetch();
            commentList = res.stream().map(e -> commentMapper.entityToDto(e)).collect(Collectors.toList());
            redisTemplate.opsForValue().set(RedisKeyPrefix.COMMENTLIST,commentList);
        }
        for(CommentDto project:commentList){
            if(project.getCreateTime() != null){
                project.setShowCreateTime(CommonUtil.getDateByFormat(project.getCreateTime(),"yyyy-MM-dd"));
            }
        }
        return commentList;
    }


    /**
     * 获取子节点
     * @param id  父节点id
     * @param allMenu 所有菜单列表
     * @return 每个根节点下，所有子菜单列表
     */
    private List<CommentDto> getChild(Integer id, List<CommentDto> allMenu) {
        //子菜单
        List<CommentDto> childList = new ArrayList<>();
        for(CommentDto menu:allMenu){
            if(menu.getReplyForId().equals(id)){
                childList.add(menu);
            }
        }

        //递归
        for(CommentDto menu:childList){
            menu.setChildren(getChild(menu.getId(),allMenu));
        }

        if(childList.size() == 0){
            //如果节点下没有子节点，返回一个空List（递归退出）
            return new ArrayList<CommentDto>();
        }

        return childList;
    }
}
